package cn.coisini.model.common.dtos;

import cn.coisini.model.common.enums.ResultEnum;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

import java.io.Serializable;

/**
 * @author xiangshaw
 * Description: 通用结果返回类
 */
@Getter
@Setter
@Tag(name = "通用结果返回类")
@ToString
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Result<T> implements Serializable {
    @Schema(description = "请求地址")
    private String host;

    @Schema(description = "业务状态码")
    private Integer code;

    @Schema(description = "业务状态信息")
    private String message;

    @Schema(description = "业务数据")
    private T data;

    @Schema(description = "续期后的token")
    private String renewalToken;

    /**
     * 无参构造函数，默认设置状态码为200
     */
    public Result() {
        this.code = 200;
    }

    /**
     * 构造函数，仅设置状态码和数据
     *
     * @param code 状态码
     * @param data 数据
     */
    public Result(Integer code, T data) {
        this.code = code;
        this.data = data;
    }

    /**
     * 构造函数，设置状态码、信息和数据
     *
     * @param code    状态码
     * @param message 信息
     * @param data    数据
     */
    public Result(Integer code, String message, T data) {
        this(code, data);
        this.message = message;
    }

    /**
     * 构造函数，设置状态码和信息
     *
     * @param code    状态码
     * @param message 信息
     */
    public Result(Integer code, String message) {
        this.code = code;
        this.message = message;
    }

    /**
     * 静态方法生成成功结果对象
     *
     * @param code    状态码
     * @param message 信息
     * @param <T>     泛型类型
     * @return 成功结果对象
     */
    public static <T> Result<T> ok(int code, String message) {
        return new Result<>(code, message);
    }

    /**
     * 仅返回数据的成功结果对象
     *
     * @param data 数据
     * @param <T>  泛型类型
     * @return 成功结果对象
     */
    public static <T> Result<T> ok(T data) {
        return new Result<>(ResultEnum.SUCCESS.getCode(), ResultEnum.SUCCESS.getMessage(), data);
    }

    /**
     * 返回带信息和数据的成功结果对象
     *
     * @param data    数据
     * @param message 信息
     * @param <T>     泛型类型
     * @return 成功结果对象
     */
    public static <T> Result<T> ok(T data, String message) {
        return new Result<>(ResultEnum.SUCCESS.getCode(), message, data);
    }

    /**
     * 静态方法生成错误结果对象
     *
     * @param code    状态码
     * @param message 信息
     * @param <T>     泛型类型
     * @return 错误结果对象
     */
    public static <T> Result<T> error(int code, String message) {
        return new Result<>(code, message);
    }

    /**
     * 使用枚举生成错误结果对象
     *
     * @param enums 枚举
     * @param <T>   泛型类型
     * @return 错误结果对象
     */
    public static <T> Result<T> error(ResultEnum enums) {
        return new Result<>(enums.getCode(), enums.getMessage());
    }

    /**
     * 使用枚举和消息生成错误结果对象
     *
     * @param enums   枚举
     * @param message 信息
     * @param <T>     泛型类型
     * @return 错误结果对象
     */
    public static <T> Result<T> error(ResultEnum enums, String message) {
        return new Result<>(enums.getCode(), message);
    }

    /**
     * 返回带数据和信息的错误结果对象
     *
     * @param data    数据
     * @param message 信息
     * @param <T>     泛型类型
     * @return 错误结果对象
     */
    public static <T> Result<T> error(T data, String message) {
        return new Result<>(ResultEnum.FAIL.getCode(), message, data);
    }

    /**
     * 设置错误结果并返回对象
     *
     * @param code    状态码
     * @param message 信息
     * @return 错误结果对象
     */
    public Result<T> errorResult(Integer code, String message) {
        this.code = code;
        this.message = message;
        return this;
    }

    /**
     * 设置成功结果并返回对象
     *
     * @param code 状态码
     * @param data 数据
     * @return 成功结果对象
     */
    public Result<T> okResult(Integer code, T data) {
        this.code = code;
        this.data = data;
        return this;
    }

    /**
     * 设置成功结果并返回对象，带信息
     *
     * @param code    状态码
     * @param data    数据
     * @param message 信息
     * @return 成功结果对象
     */
    public Result<T> okResult(Integer code, T data, String message) {
        this.code = code;
        this.data = data;
        this.message = message;
        return this;
    }

    /**
     * 设置成功结果并返回对象
     *
     * @param data 数据
     * @return 成功结果对象
     */
    public Result<T> okResult(T data) {
        this.data = data;
        return this;
    }
}